/*
 * NotaEditor.java
 *
 * Created on 18-dic-2007, 23:11:20
 *
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jschoolmanagerportable.gui.model;

import java.awt.Color;
import java.awt.Component;
import java.awt.Toolkit;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultCellEditor;
import javax.swing.JFormattedTextField;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.text.DefaultFormatterFactory;
import javax.swing.text.NumberFormatter;
import jschoolmanagerportable.JSchoolManagerPortableApp;
import jschoolmanagerportable.JSchoolManagerPortableView;
import jschoolmanagerportable.gui.NotasAdminView;

/**
 *
 * @author Administrador
 */
public class NotaEditor extends DefaultCellEditor {

    JFormattedTextField ftf;
    DecimalFormat decimalFormat;
    private Double minimum;
    private Double maximum;
    private boolean DEBUG = false;
    private NotasAdminView view;
    private int column;
    private int row;

    public NotaEditor(NotasAdminView view, double min, double max) {
        super(new JFormattedTextField());
        this.view = view;
        Component comp = this.getComponent();
        ftf = (JFormattedTextField) comp;
        minimum = new Double(min);
        maximum = new Double(max);

        //Set up the editor for the Double cells.
        decimalFormat = new DecimalFormat("0.0");
        NumberFormatter decFormatter = new NumberFormatter(decimalFormat);
        decFormatter.setFormat(decimalFormat);
        ftf.setFormatterFactory(new DefaultFormatterFactory(decFormatter));
        ftf.setValue(minimum);
        ftf.setHorizontalAlignment(JTextField.TRAILING);
        ftf.setFocusLostBehavior(JFormattedTextField.PERSIST);

        ftf.addKeyListener(new java.awt.event.KeyAdapter() {

            public void keyReleased(java.awt.event.KeyEvent evt) {
                validaEntrada(evt);
            }
        });


    }

    //Override to invoke setValue on the formatted text field.
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
        this.row = row;
        this.column = column;
        JFormattedTextField ftf = (JFormattedTextField) super.getTableCellEditorComponent(table, value, isSelected, row, column);
        ftf.setBackground(Color.GREEN);
        ftf.selectAll();
        return ftf;
    }

    //Override to ensure that the value remains an Double.
    public Object getCellEditorValue() {
        JFormattedTextField ftf = (JFormattedTextField) getComponent();
        Object o = ftf.getValue();
        if (o instanceof Double) { // Si digitan el valor decimal
            return o;
        } else if (o instanceof Number) { // Si lo hacen con un entero
            String strNota = String.valueOf(o);
            Double dbl = Double.valueOf(strNota) / 10; //Entero a decimal...brillante! :P
            return dbl;
        } else {
            if (DEBUG) {
                JSchoolManagerPortableApp.getLog().warning("getCellEditorValue: o isn't a Number");
            }
            try {
                return decimalFormat.parseObject(o.toString());
            } catch (ParseException exc) {
                JSchoolManagerPortableApp.getLog().warning("getCellEditorValue: can't parse o: " + o);
                return null;
            }
        }
    }

    //Override to check whether the edit is valid,
    //setting the value if it is and complaining if
    //it isn't.  If it's OK for the editor to go
    //away, we need to invoke the superclass's version
    //of this method so that everything gets cleaned up.
    public boolean stopCellEditing() {
        JFormattedTextField ftf = (JFormattedTextField) getComponent();
        if (ftf.isEditValid()) {
            try {
                ftf.commitEdit();
            } catch (java.text.ParseException exc) {
            }
        } else {
            //text is invalid
            if (!userSaysRevert("El valor de la nota debe estar entre " + minimum + " y " + maximum)) {
                //user wants to edit
                return false; //don't let the editor go away
            }
        }
        return super.stopCellEditing();
    }

    /**
     * Lets the user know that the text they entered is
     * bad. Returns true if the user elects to revert to
     * the last good value.  Otherwise, returns false,
     * indicating that the user wants to continue editing.
     */
    protected boolean userSaysRevert(String mensaje) {
        Toolkit.getDefaultToolkit().beep();
        ftf.selectAll();
        Object[] options = {"Editar", "Deshacer"};
        int answer = JOptionPane.showOptionDialog(SwingUtilities.getWindowAncestor(ftf), mensaje, "Nota NO valida", JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE, null, options, options[1]);

        if (answer == 1) {
            //Revert!
            ftf.setValue(ftf.getValue());
            return true;
        }
        return false;
    }

    private void validaEntrada(java.awt.event.KeyEvent evt) {
        JFormattedTextField txt = (JFormattedTextField) evt.getSource();
        if (txt.getText().length() == 2) {
            String texto = txt.getText();
            double numero = 0;
            try {
                numero = Double.valueOf(texto.substring(0, 1) + "." + texto.substring(1, 2));
            } catch (Exception e) {
                boolean resp = userSaysRevert("La entrada no es un número");
                if (resp) {
                    try {
                        txt.setValue(10); // TODO: Cambiar por el valor anterior
                        txt.commitEdit(); //stop editing                    
                        txt.postActionEvent(); //stop editing
                        notaSiguiente(0);
                    } catch (ParseException ex) {
                        Logger.getLogger(NotaEditor.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                return;
            }

            if (numero < minimum || numero > maximum) {
                userSaysRevert("La nota debe estar entre: " + minimum + " y " + maximum);
                try {
                    txt.setValue(10); // TODO: Cambiar por el valor anterior
                    txt.commitEdit(); //stop editing
                    txt.postActionEvent(); 
                    notaSiguiente(0);
                    return;
                } catch (ParseException ex) {
                    Logger.getLogger(NotaEditor.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

            try {
                txt.commitEdit(); //so use it.
                txt.postActionEvent(); //stop editing
            } catch (java.text.ParseException exc) {
            }
            notaSiguiente(1);
        }
    }

    private void notaSiguiente(int cantidad) {
        view.notaSiguiente(this.column, this.row, cantidad);
    }
}
